#include <SDL.h>
#include <SDL_image.h>
#include <math.h>
#include "scr_game.h"
#include "scr_game_state.h"
#include "scr_game_state_manager.h"
#include "scr_resource_manager.h"
#include "scr_texture.h"
#include "scr_font.h"
#include "scr_music.h"
#include "scr_keyboard.h"
#include "scr_mouse.h"
#include "scr_basic_sprite.h"
#include "scr_math.h"
#include "scr_profiler.h"

class TestState : public SCRGameState
{
public:
	
	TestState()
		: m_X(FXIntToFX(1024))
		, m_Y(FXIntToFX(1024))
		, m_WorldX(FXIntToFX(1024 - 512))
		, m_WorldY(FXIntToFX(1024 - 384))
		, m_Angle(0)
		, m_Animation(0)
		, m_SpriteMarineTorso(NULL)
		, m_SpriteMarineLegs(NULL)
	{
	}

	virtual void OnInitialize()
	{
		m_Background = m_pGame->GetResourceManager()->GetTexture("images/background.png");
		m_Font = m_pGame->GetResourceManager()->GetFont("fonts/appleberry_with_cyrillic.ttf", 56);
		m_Music = m_pGame->GetResourceManager()->GetMusic("music/music01.ogg");
		m_MarineTorso = m_pGame->GetResourceManager()->GetTexture("images/marine_top.png", true);
		m_MarineLegs = m_pGame->GetResourceManager()->GetTexture("images/marine_bottom.png", true);
		m_SpriteMarineTorso = new SCRBasicSprite(m_MarineTorso, 64, 64, 32, 32);
		m_SpriteMarineLegs = new SCRBasicSprite(m_MarineLegs, 64, 64, 32, 32);
		m_Music->Play();
	}

	virtual void OnUpdate(const int& Delta)
	{
		SCR_PROFILER(OnUpdate);

		if (SCRKeyboard::IsPressed(SDLK_LEFT))
		{
			m_Angle -= 1024;
		}
		else if (SCRKeyboard::IsPressed(SDLK_RIGHT))
		{
			m_Angle += 1024;
		}

		m_Angle &= 0xFFFF;

		if (SCRKeyboard::IsPressed(SDLK_UP))
		{
			m_X += SCRMath::FXSin(m_Angle) * 4;
			m_Y -= SCRMath::FXCos(m_Angle) * 4;
			m_Animation++;
			if (m_Animation > 60) m_Animation -= 60;
		}
		else if (SCRKeyboard::IsPressed(SDLK_DOWN))
		{
			m_X -= SCRMath::FXSin(m_Angle) * 4;
			m_Y += SCRMath::FXCos(m_Angle) * 4;
			m_Animation--;
			if (m_Animation < 0) m_Animation += 60;
		}

		if (m_X < 0) m_X = 0;
		if (m_X > FXIntToFX(2048)) m_X = FXIntToFX(2048);
		if (m_Y < 0) m_Y = 0;
		if (m_Y > FXIntToFX(2048)) m_Y = FXIntToFX(2048);

		if (m_X < m_WorldX + FXIntToFX(256) && m_WorldX > 0)
		{
			m_WorldX -= (m_WorldX + FXIntToFX(256)) - m_X;
		}

		if (m_X > m_WorldX + FXIntToFX(1024 - 256) && m_WorldX < FXIntToFX(2048 - 1024))
		{
			m_WorldX += m_X - (m_WorldX + FXIntToFX(1024 - 256)); 
		}

		if (m_Y < m_WorldY + FXIntToFX(256) && m_WorldY > 0)
		{
			m_WorldY -= (m_WorldY + FXIntToFX(256)) - m_Y;
		}

		if (m_Y > m_WorldY + FXIntToFX(768 - 256) && m_WorldY < FXIntToFX(2048 - 768))
		{
			m_WorldY += m_Y - (m_WorldY + FXIntToFX(768 - 256));
		}

		if (SCRKeyboard::IsClicked(SDLK_ESCAPE))
		{
			m_pGame->GetStateManager()->Pop();
		}
	}

	virtual void OnRender(const int& Delta)
	{
		SCR_PROFILER(OnRender);

		if (m_Background)
		{
			m_Background->Draw(FXFXToInt(0 - m_WorldX), FXFXToInt(0 - m_WorldY));
		}

		float Angle = (float)m_Angle / (float)FX32_TABLE_SIZE;

		const int OffsetX = (const int)FXFXToInt(m_X - m_WorldX);
		const int OffsetY = (const int)FXFXToInt(m_Y - m_WorldY);

		if (m_SpriteMarineLegs)
		{
			int Frame = (int)(Angle * 8.0f);
			m_SpriteMarineLegs->Draw(OffsetX, OffsetY, m_Animation / 15, Frame);
		}

		if (m_SpriteMarineTorso)
		{
			int Frame = (int)(Angle * 16.0f);
			m_SpriteMarineTorso->Draw(OffsetX, OffsetY, 0, Frame);
		}

		for (int IdxX = 0; IdxX < 40; ++IdxX)
		{
			for (int IdxY = 0; IdxY < 25; ++IdxY)
			{
				int LegFrame = (int)(Angle * 8.0f);
				m_SpriteMarineLegs->Draw(OffsetX - 512 + (IdxX * 25), OffsetY - 384 + (IdxY * 30), m_Animation / 15, LegFrame);
				int TorsoFrame = (int)(Angle * 16.0f);
				m_SpriteMarineTorso->Draw(OffsetX - 512 + (IdxX * 25), OffsetY - 384 + (IdxY * 30), 0, TorsoFrame);
			}
		}
	}

	virtual void OnTerminate()
	{
		if (m_SpriteMarineTorso)
		{
			delete m_SpriteMarineTorso;
			m_SpriteMarineTorso = NULL;
		}

		if (m_SpriteMarineLegs)
		{
			delete m_SpriteMarineLegs;
			m_SpriteMarineLegs = NULL;
		}
	}

private:

	SCRTexturePtr m_Background;
	SCRFontPtr m_Font;
	SCRMusicPtr m_Music;
	SCRTexturePtr m_MarineTorso;
	SCRTexturePtr m_MarineLegs;
	SCRBasicSprite* m_SpriteMarineTorso;
	SCRBasicSprite* m_SpriteMarineLegs;
	FX32 m_X;
	FX32 m_Y;
	FX32 m_WorldX;
	FX32 m_WorldY;
	FX32 m_Angle;
	int m_Animation;	
};

int main(int argc, char* args[])
{
	SCRGame::CreateInstance();

	SCRGame* pGame = SCRGame::GetInstance();
	
	if (pGame->Initialize())
	{
		pGame->GetStateManager()->Push<TestState>();
		pGame->Run();
	}
	pGame->Terminate();

	SCRGame::DestroyInstance();

	return 0;
}
